/*!
 * @file prochan.h
 * @brief Handles processes.
 */

/* State definitions to be used in pcb */
#define RUNNING	          1
#define READY             2
#define BLOCKED           3
#define SUSPENDED_READY   4
#define SUSPENDED_BLOCKED 5

/* Constant for stack size */
#define SYS_STACK_SIZE        1024

/* Class definitions to be used in pcb */
#define SYSTEM      1
#define APPLICATION 2

/* Structure for process control block */
typedef struct PCB{
	char name[10]; // name of process
	int processClass; // class of process, see Class definitions
	int priority; // priority of the process (-128 through 127)
	unsigned char state; // present state of process, see State definitions
	unsigned char *stackBase; // base of process stack area
	unsigned char *stackTop; // top of process stack area
	int stackSize; // the size of the stack
	unsigned char *loadAddress;
	unsigned char *execAddress;
	struct PCB *prev; // previous pcb in linked list
	struct PCB *next; // next pcb in linked list
	} pcb;

/* Structure to be used as a base for pcb linked list */
typedef struct {
	int currCount; // the current number of processes in the list
	pcb *first; // first element in the list
	pcb *last; // last element in the list
} pcbBase;

/*!
 * Context for process stack.
 */
typedef struct context {
    unsigned int BP, DI, SI, DS, ES;
    unsigned int DX, CX, BX, AX;
    unsigned int IP, CS, FLAGS;
} context;

/*!
 * Parameters for process stack.
 */
typedef struct params{
  int op_code;
  int device_id;
  unsigned char *buf_addr;
  int *count_addr;
} params;

typedef struct IOD {
	struct IOD *next;
	char *name;
	pcb *process;
	int operation;
	int device;
	char *buff;
	int *count;
} iod;

typedef struct IOCB {
	iod *head;
	iod *tail;
	int count;
} iocb;

/* Function prototypes */
pcb* allocatePCB(int memorySize, int offset, int stackSize);
void freePCB(pcb *block);
pcb* setupPCB(char *name, int priority, int processClass, int memorySize, int offset, int stackSize);
pcb* findPCB(char *name);
void insertPCB(pcb *block);
void removePCB(char *name);
void interrupt sys_call();
void interrupt dispatch();
int loader(char *name, int priority, int stackSize);
void processIORequest(iod *tempIOD, int device);
void ioSceduler();